package br.org.bertol.mestrado.engine.optimisation.hillclimbing;

import java.util.Collections;

import br.org.bertol.mestrado.engine.optimisation.Operacao;
import br.org.bertol.mestrado.engine.optimisation.entity.Path;

/**
 * Conjunto de operações para manipualação de posição de um caminho.
 * @author contaqualquer
 */
public enum Operador implements Operacao<Path> {

    /**
     * Operador de permuta aletória.
     */
    PERMUTA_ALEATORIA {

        /**
         * {@inheritDoc}
         */
        public void execute(final Path path) {

            int controlePermuta = path.getControlePermuta();

            // primeira permuta aleat�ria
            int pointer1 = Double.valueOf(
                                          path.getFator().nextDouble()
                    * path.getRoute().size()).intValue();

            int pointer2 = Double.valueOf(
                                          path.getFator().nextDouble()
                    * path.getRoute().size())
                    .intValue();

            controlePermuta = pointer1;

            Collections.swap(path.getRoute(), pointer1, pointer2);

            // segunda permut aaleat�ria
            pointer1 = Double.valueOf(
                                      path.getFator().nextDouble()
                    * path.getRoute().size())
                    .intValue();

            pointer2 = Double.valueOf(
                                      path.getFator().nextDouble()
                    * path.getRoute().size())
                    .intValue();

            controlePermuta = pointer1;

            Collections.swap(path.getRoute(), pointer1, pointer2);

            path.setControlePermuta(controlePermuta);

            path.setX1(pointer1);

            path.setX2(pointer2);
        }
        },
    /**
     * Operador de permuta cadência 2.
     */
    PERMUTA_CADENCIA_2 {

        /**
         * {@inheritDoc}
         */
        public void execute(final Path path) {
            int controlePermuta = path.getControlePermuta();

            if (controlePermuta == 0) {
                controlePermuta = path.getRoute().size() - 1;
            }

            int pointer1 = controlePermuta;

            int pointer2 = controlePermuta - 1;

            // caso tenha passado o �ltimo �ndice
            // volta para o come�o da lista
            if (pointer1 < 0) {
                pointer1 = (path.getRoute().size() - 1) + pointer1;
            }

            if (pointer2 < 0) {
                pointer2 = (path.getRoute().size() - 1) + pointer2;
            }

            controlePermuta = pointer1 - 3;

            Collections.swap(path.getRoute(), pointer1, pointer2);

            path.setControlePermuta(controlePermuta);

            path.setX1(pointer1);

            path.setX2(pointer2);
        }
        },
    /**
     * Operador de permuta cadência 3.
     */
    PERMUTA_CADENCIA_3 {

        /**
         * {@inheritDoc}
         */
        public void execute(final Path path) {

            int controlePermuta = path.getControlePermuta();

            if (controlePermuta == 0) {
                controlePermuta = path.getRoute().size() - 1;
            }

            int pointer1 = controlePermuta;

            int pointer2 = controlePermuta - 2;

            // caso tenha passado o �ltimo �ndice
            // volta para o come�o da lista
            // caso tenha passado o �ltimo �ndice
            // volta para o come�o da lista
            if (pointer1 < 0) {
                pointer1 = (path.getRoute().size() - 1) + pointer1;
            }

            if (pointer2 < 0) {
                pointer2 = (path.getRoute().size() - 1) + pointer2;
            }

            controlePermuta = pointer1 - 2;

            Collections.swap(path.getRoute(), pointer1, pointer2);

            path.setControlePermuta(controlePermuta);

            path.setX1(pointer1);

            path.setX2(pointer2);
        }
        };
}
